package htdi.act.usrmgr.endpoints;

import act.controller.annotation.UrlContext;
import act.db.DbBind;
import act.db.jpa.JPAQuery;
import act.db.util.Page;
import act.inject.DefaultValue;
import htdi.act.usrmgr.models.User;
import org.osgl.$;
import org.osgl.mvc.annotation.*;
import org.osgl.util.S;

import javax.inject.Inject;
import javax.validation.constraints.NotNull;

/**
 * Endpoints for user relevant services.
 */
@UrlContext("users")
public class UserService extends ServiceBase {

    @Inject
    private User.Dao userDao;

    /**
     * List users with filter and pagination support.
     *
     * @param q
     *      the query string, fuzzy matches firstName or lastName
     * @param page
     *      the page number
     * @param pageSize
     *      the size of one page
     * @return a page of users filtered
     */
    @GetAction
    public Page<User> list(String q, Integer page, @DefaultValue("10") Integer pageSize) {
        JPAQuery<User> query, countQuery;
        if (S.notBlank(q)) {
            if (!q.contains("%")) {
                q = "%" + q + "%";
            }
            query = userDao.q("select u from User u where u.firstName like ?1 or u.lastName like ?2", q, q);
            countQuery = userDao.q("select count (u) from User u where u.firstName like ?1 or u.lastName like ?2", q, q);
        } else {
            query = userDao.q();
            countQuery = query;
        }
        if (null != page) {
            query.offset(pageSize * page);
        }
        query.limit(pageSize);
        return Page.of(query.fetch(), countQuery.count());
    }

    /**
     * Get a specific user by `id`
     *
     * @param user
     *      the URL parameter to specify user id
     * @return the user found by `id` specified or 404 if not found
     */
    @GetAction("{user}")
    public User get(@DbBind User user) {
        return user;
    }

    /**
     * Update a user by id.
     * @param user
     *      the URL parameter to specify the id of user to be updated.
     * @param data
     *      the date to update the user
     */
    @PutAction("{user}")
    public void update(@NotNull @DbBind User user, User data) {
        userDao.save($.merge(data).filter("-email,-password").to(user));
    }

    /**
     * Delete a user by id.
     * @param id
     *      the URL parameter to specify the id of the user to be deleted
     */
    @DeleteAction("{id}")
    public void delete(Long id) {
        userDao.deleteById(id);
    }

}
